package gov.nasa.anml.lifted;

import java.util.ArrayList;

import gov.nasa.anml.PDDL;
import gov.nasa.anml.State;
import gov.nasa.anml.PDDL.CompoundEffect;
import gov.nasa.anml.utility.SimpleBoolean;
import gov.nasa.anml.utility.SimpleObject;
import gov.nasa.anml.utility.SimpleString;
import gov.nasa.anml.utility.SimpleVoid;

public class Exists extends Block {
	
	public Exists(Scope parent, SimpleString n) {
		super(parent,n);
	}
	
	public boolean apply(State p, int contextID, State c) {
		statementLoop: for(int i=0; i < statements.size(); ++i) {
			Statement s = statements.get(i);
			for(int j=0; j < 1; ++j) {
			//test each binding...
				if (s.apply(p,contextID,c))
					continue statementLoop;
			}
			return false;
		}
		return true;
	}
	
	public TypeCode typeCode() {
		return TypeCode.Boolean;
	}
	
	public History<SimpleVoid> storage(State p, State c) {
		return null;
	}
	
	public ANMLBoolean value(State p) {
		statementLoop: for(int i=0; i < statements.size(); ++i) {
			Statement s = statements.get(i);
			for(int j=0; j < 1; ++j) {
			//test each binding...
				if (s.apply(p,0,null))
					continue statementLoop;
			}
			return ANMLBoolean.False;
		}
		return ANMLBoolean.True;
	}
	
	static int exists_count=0;
	public void translateDecl(PDDL pddl, Interval unit) {
		if (asPDDLAction != null)
			return;
		
		if ( name == null || name.length == 0) {
			name = new SimpleString("exists_" + ++exists_count);
		}
		
		super.translateDecl(pddl,unit);
	}
	
	public void translateStmt(PDDL pddl, Interval unit, PDDL.Time part) {
		if (asPDDLAction == null)
			translateDecl(pddl,unit);
		
		//part = PDDL.getPart(unit,this);
		// this is wrong, because, the internal start/duration/end etc.
		// are for the endpoints of the compiled action, but the interval that this is timed over
		// wraps this object already -- Action.statements.TimedStatement.Exists.statements
		// is the hierarchy, abusing notation.
		//
		// the two intervals are very closely related.
		
		
		ArrayList<PDDL.BooleanExpression> conditions = unit.getPDDLConditions(); 
		ArrayList<PDDL.Effect> effects = unit.getPDDLEffects();
		ArrayList<PDDL.BooleanExpression> myConditions = getPDDLConditions(); 
		ArrayList<PDDL.Effect> myEffects = getPDDLEffects();

		
		PDDL.Exists e;
		switch(part) {
		case All:
		case Interim:
		case StartHalf:
		case EndHalf:
			_translateStmt(pddl,this,PDDL.Time.Interim);
			e = pddl.new Exists(getPDDLParameters(),this.getPDDLExecuting().trivialRef());
			conditions.add(pddl.wrap(PDDL.Time.Interim,e));
			myConditions.add(pddl.wrap(PDDL.Time.Interim,unit.getPDDLExecuting().trivialRef()));
			break;
		default:
			System.err.println("Existentials over anything besides (all) will likely compile incorrectly, especially if they contain effects.");
			myConditions.clear();
			_translateStmt(pddl,this,PDDL.Time.Timeless);
			assert myEffects.size() == 0 : "Existential effects not on (all) are ignored.";
			e = pddl.new Exists(getPDDLParameters(),pddl.wrap(PDDL.Op.and,myConditions));
			conditions.add(pddl.wrap(part,e));
			pddl.actions.remove(this);
			pddl.predicates.remove(this.getPDDLExecuting());
		}
	}


	public PDDL.Expression translateLValue(PDDL pddl, Interval unit) {
		System.err.println("Shouldn't happen");
		return super.translateLValue(pddl,unit);
	}	
}
